package br.pucrio.inf.tamdera.prolog;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.emf.common.util.EList;

import br.pucrio.inf.tamdera.ConceptDeclaration;
import br.pucrio.inf.tamdera.Constants;
import br.pucrio.inf.tamdera.DependencyRuleDeclaration;
import br.pucrio.inf.tamdera.Paragraph;
import br.pucrio.inf.tamdera.RulesSpecification;
import br.pucrio.inf.tamdera.prolog.qbeans.PrologAntiErosionQueryBean;
import br.pucrio.inf.tamdera.prolog.qbeans.PrologQueryBean;
import br.pucrio.inf.tamdera.prolog.utils.PrologIntegrationConstants;

public class PrologAntiErosionQueryVisitor 
{
	
	public PrologAntiErosionQueryVisitor() 
	{
		antiErosionQueries = new ArrayList<PrologQueryBean>();
		
	}
	

	protected List<PrologQueryBean> antiErosionQueries;

	protected void _generateQuery(final RulesSpecification spec) 
	{
		EList<Paragraph> paragraphs = spec.getParagraphs();
		for (Paragraph para : paragraphs )
		{
			generateQuery ( para );
		}
	}

	protected void _generateQuery(final DependencyRuleDeclaration dependDecl) 
	{
		ConceptDeclaration source =  dependDecl.getSource();
		ConceptDeclaration target =  dependDecl.getTarget();
		
		String sourceName = source.getName();
		String targetName = target.getName();
		
		//cannot, only-can, 
		String type = dependDecl.getType();
		if (type.equals( Constants.DEPENDENCY_TYPE_CAN))
		{
			type = Constants.DEPENDENCY_TYPE_ONLY_CAN;
		}
		
		//relation
		String relation = dependDecl.getRelation();
		
		String template = getTemplateOfQuery( relation, type );
		
		String query = String.format ( template, type, relation, 
				PrologIntegrationConstants.VIOLATION, sourceName, targetName );
		
		antiErosionQueries.add( new PrologAntiErosionQueryBean(query, dependDecl) );
	}
	
	/**
	 * Some relations type needs more parameters than 
	 * @param relationType
	 * @param type 
	 * @return the template of a query considering the type of relation 
	 */
	public String getTemplateOfQuery ( String relationType, String dependencyType )
	{
		
		
		String templateQuery = "%s_%s_%s";
		
		//add Concept1 Concept2, SOURCE, TARGET
		
		List<String> parameterString = getResultParametersOfQuery( relationType, dependencyType );
		// c1 and c2 template
		templateQuery += "('%s','%s',";
		
		int index = 0;
		for (String parameter : parameterString )
		{
			templateQuery += parameter;
			if (index < parameterString.size() - 1 )
			{
				templateQuery += ",";
			}
			index++;
		}
		templateQuery += ").";
		return templateQuery;
	}


	private List<String> getResultParametersOfQuery(String relationType,
			String dependencyType) 
	{
		// if it a must dependency, the query will return only the source who has not the mandatory dependency
		if ( dependencyType.equals( Constants.DEPENDENCY_TYPE_MUST))
		{
			return Constants.MUST_RESULTS;
		}
		
		//CANNOT e ONLY
		List<String> parameterString = Constants.DEFAULT_RESULTS;
		if ( relationType.equals( Constants.DEPENDENCY_RELATION_DECLARES ))
		{
			parameterString = Constants.DECLARE_RESULTS;
		}
		else if ( relationType.equals( Constants.DEPENDENCY_RELATION_INVOKES )) 
		{
			parameterString = Constants.INVOKES_RESULTS;
		}
		else if ( relationType.equals( Constants.DEPENDENCY_RELATION_CREATES ))
		{
			parameterString = Constants.CREATES_RESULTS;
		}

		return parameterString;
	}

	public void generateQuery(final Object object) 
	{
		if (object instanceof DependencyRuleDeclaration)
		{
			_generateQuery((DependencyRuleDeclaration)object);
		} 
		else if (object instanceof RulesSpecification) 
		{
			_generateQuery((RulesSpecification)object);
		} 
		else 
		{
		}
	}


	public List<PrologQueryBean> getQueries() {
		return antiErosionQueries;
	}

	public void setQueries(List<PrologQueryBean> queries) {
		this.antiErosionQueries = queries;
	}

}
